﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace NeturalMath.Expressions
{
    public class NodeFindingVisitor:MathExpressionVisitor<IEnumerable<MathExpression>>
    {
        public NodeFindingVisitor(Func<MathExpression, bool> searchExpression,MathRuntime runtime) 
            : base(runtime)
        {
            SearchExpression = searchExpression;
        }

        public Func<MathExpression, bool> SearchExpression { get; private set; }


        protected override IEnumerable<MathExpression> VisitAssignment(AssignmentExpression expression)
        {
            if (SearchExpression(expression))
                yield return expression;

            foreach (var e in Visit(expression.Assignment))
                yield return e;

            foreach (var e in Visit(expression.Target))
                yield return e;
        }

        protected override IEnumerable<MathExpression> VisitBinaryOperator(BinaryOperatorExpression expression)
        {
            if (SearchExpression(expression))
                yield return expression;

            foreach (var e in Visit(expression.Left))
                yield return e;

            foreach (var e in Visit(expression.Right))
                yield return e;
        }

        protected override IEnumerable<MathExpression> VisitConstant(ConstantValueExpression expression)
        {
            if (SearchExpression(expression))
                yield return expression;
        }

        protected override IEnumerable<MathExpression> VisitDomain(DomainExpression expression)
        {
            if (SearchExpression(expression))
                yield return expression;

            foreach (var e in expression.Expressions)
                foreach (var c in Visit(e))
                    yield return c;
        }


        protected override IEnumerable<MathExpression> VisitFunctionCall(FunctionUseExpression expression)
        {
            if (SearchExpression(expression))
                yield return expression;

            foreach (var p in expression.Parameters)
                foreach (var e in Visit(p))
                    yield return expression;
        }

        protected override IEnumerable<MathExpression> VisitImportKeyword(ImportKeywordExpression expression)
        {
            if (SearchExpression(expression))
                yield return expression;
        }

        protected override IEnumerable<MathExpression> VisitMemberLookup(LookupExpression expression)
        {
            if (SearchExpression(expression))
                yield return expression;
        }

        protected override IEnumerable<MathExpression> VisitDefKeyword(DefKeywordExpression expression)
        {
            if (SearchExpression(expression))
                yield return expression;

            foreach (var e in expression.Expressions)
                foreach (var c in Visit(e))
                    yield return c;
        }

        protected override IEnumerable<MathExpression> VisitPrintKeyword(PrintKeywordExpression expression)
        {
            if (SearchExpression(expression))
                yield return expression;

            foreach (var e in expression.Expressions)
                foreach (var c in Visit(e))
                    yield return c;
        }

        protected override IEnumerable<MathExpression> VisitParameterExpression(FunctionParameterExpression expression)
        {
            if (SearchExpression(expression))
                yield return expression;

            foreach (var e in Visit(expression.DefaultValue))
                yield return e;
        }

        protected override IEnumerable<MathExpression> VisitUnaryOperator(UnaryOperatorExpression expression)
        {
            if (SearchExpression(expression))
                yield return expression;

            foreach (var e in Visit(expression.Expression))
                yield return e;
        }

        protected override IEnumerable<MathExpression> VisitDelegate(DelegateExpression expression)
        {
            if (SearchExpression(expression))
                yield return expression;
        }

        protected override IEnumerable<MathExpression> VisitSymbolicLookup(SymbolicLookupExpression expression)
        {
            if (SearchExpression(expression))
                yield return expression;
        }
    }
}
